#ifndef __VIEW_VIEW_H
#define __VIEW_VIEW_H

#include <driver/view/section.h>
#include <driver/view/screen.h>
#include <driver/view/region.h>
#include <driver/view/msg.h>
#include <os/msgpool.h>
#include <lib/list.h>

// resize view border size
#define VIEW_RESIZE_BORDER_SIZE 2
// resize view size min
#define VIEW_RESIZE_SIZE_MIN 16

// view max support size
#define VIEW_MAX_SIZE_WIDTH 1920
#define VIEW_MAX_SIZE_HEIGHT 1080

// maximum number of views
#define VIEW_NUM_MAX 32

// default msg number
#define VIEW_MSGPOOL_MSG_NUM 64

// view type
typedef enum
{
    VIEW_TYPE_FIXED = 0,
    VIEW_TYPE_WINDOWS,
    VIEW_TYPE_FLOAT,
} view_type_t;

typedef enum
{
    VIEW_ATTR_RESIZEABLE = 0x01,
    VIEW_ATTR_MOVEABLE = 0x02,
} view_attr_t;

typedef struct view
{
    list_t list;        // show list
    list_t global_list; // global list
    int id;
    int width;
    int height;
    int width_min;
    int height_min;
    int x;
    int y;
    int z;

    view_section_t *section;
    msgpool_t *msgpool;
    uint8_t type;
    uint8_t attr;

    // region set
    view_region_t drag_regions[VIEW_DRAG_REGION_NUM];
    view_region_t resize_regions;

    spinlock_t lock;
} view_t;

extern int view_top_z;


static inline int ViewMoveToTop(view_t *view)
{
    if (!view)
        return -1;
    ViewSetZ(view, view_top_z);
    return 0;
}

static inline int ViewMoveToBottom(view_t *view)
{
    if (!view)
        return -1;
    ViewSetZ(view, 0);
    return 0;
}

// move to top view under
static inline int ViewMoveUnderTop(view_t *view)
{
    if (!view)
        return -1;
    ViewSetZ(view, view_top_z - 1);
    return 0;
}

static inline int ViewMoveUpperTop(view_t *view)
{
    if (!view)
        return -1;
    ViewSetZ(view, view_top_z + 1);
    return 0;
}

static inline int ViewMoveUnderView(view_t *view, view_t *targe)
{
    if (!view || !targe)
        return -1;
    ViewSetZ(view, targe->z - 1);
    return 0;
}

static inline int ViewMoveUnpperView(view_t *view, view_t *targe)
{
    if (!view || !targe)
        return -1;
    ViewSetZ(view, targe->z + 1);
    return 0;
}

static inline int ViewHide(view_t *view)
{
    if (!view)
        return -1;

    ViewSetZ(view, -1);
    return 0;
}

static inline int ViewAddAttr(view_t *view, int attr)
{
    if (!view)
        return -1;
    view->attr |= attr;
}

static inline int ViewDelAttr(view_t *view, int attr)
{
    if (!view)
        return -1;
    view->attr &= ~attr;
}

#define ViewTryPutMsg(view,msg) ViewPutMsg((view),(msg),VIEW_MSG_NOWAIT)

view_t *ViewFindByZ(int z);
list_t *ViewGetShowList();
view_t *ViewFindById(int id);
void ViewClear(view_t *view);
void ViewMaxSizeRepair(int *width, int *height);

void *ViewGetVramStart(view_t *view);
size_t ViewGetVramSize(view_t *view);
int ViewSetSizeMin(view_t *view, int width, int height);

int ViewInit();
void ViewExit();
view_t *ViewCreate(int x, int y, int width, int height, int type);
int ViewDestroy(view_t *view);

int ViewSetType(view_t *view, int type);
int ViewGetType(view_t *view);

int ViewGetMsg(view_t *view, void *buff, int flags);
int ViewPutMsg(view_t *view, void *buff, int flags);

int ViewMoveToTop(view_t *view);
int ViewMoveToBottom(view_t *view);
int ViewMoveUnpperView(view_t *view, view_t *targe);
int ViewMoveUnderView(view_t *view, view_t *targe);
int ViewHide(view_t *view);

int ViewResize(view_t *view, int x, int y, uint32_t width, uint32_t height);
view_t *ViewGetTop();
int ViewSetXY(view_t *view, int x, int y);
int ViewShow(view_t *view);
int ViewSetDragRegion(view_t *view, view_region_t *region);
void ViewSetZ(view_t *view, int z);
int ViewDragRectCheck(view_t *view, int x, int y);

#endif